home *** CD-ROM | disk | FTP | other *** search
Text File | 1990-06-07 | 29.5 KB | 1,063 lines |
- /* Maintain a Project chart in a Window. The ProjWindow is
- responsible for all drawing of the project. The window
- has full scrolling and supports a keyboard interface.
- If topMethod or botMethod are set, then the corresponding
- method will be executed for each activity while displaying
- the project.
-
- ProjWindow descends from class Window and inherits all of
- its instance variables and methods.
-
- All strings are defined as resources for easy translation.
- */!!
-
- inherit(Window, #ProjWindow, #(project /* the project */
- fileName /* of the project */
- actions /* menu actions table */
- dirty /* true if not saved */
- view /* normal or zoomed */
- boxHeight /* based on scrnsize */
- boxWidth /* adjustable for zoom */
- boxHSpace /* adjustable */
- activWidth /* adjustable */
- hScrollPos /* horiz scroll posn */
- vScrollPos /* vert scroll posn */
- maxVisCol /* max visible col */
- maxVisRow /* max visible row */
- methTable /* table of methods */
- topMethod /* offset into table */
- botMethod /* offset into table */
- gw /* a GanttWindow */
- /* these are new for dragging */
- dragDC /* for drawing */
- anchorPt /* starting point */
- oldPt /* end point */
- ), 2, nil)!!
-
- now(ProjWindowClass)!!
-
- /* Return the name of this class's MS-Windows window class
- either for registration or new window creation. */
- Def wndClass(self)
- { ^"ProjWindow" }!!
-
- /* Create a new window class Struct.
- Change the cursor to a cross. */
- Def newWClass(self, lpCl, lpIcon | wc)
- { wc := newWClass(self:WindowClass, lpCl, lpIcon);
- putWord(wc, Call LoadCursor(0, IDC_CROSS), 14);
- ^wc;
- } !!
-
- now(ProjWindow)!!
-
- /* Allow the user to change the printer setup. */
- Def printerSetup(self | prn)
- {
- prn := new(Printer);
- getPrinterParms(prn);
- deviceMode(prn, self);
- }
- !!
-
- /* Respond to menu choice to run a program.
- By default, run MSDOS executive shell.*/
- Def run(self | dlg, progName)
- {
- dlg := new(InputDialog, "Run","Program name:","MSDOS.EXE");
- if runModal(dlg, INPUT_BOX, self) == IDOK
- progName:=getText(dlg);
- exec(progName);
- endif;
- }!!
-
- /* Handles menu choice to set colors. Global variables
- CritColor and SlackColor determine the application
- colors. */
- Def toggleColor(self)
- {
- if CritColor <> BLACK
- unCheckMenuItem(self, PW_COLOR);
- CritColor := BLACK;
- SlackColor := BLACK;
- else
- checkMenuItem(self, PW_COLOR);
- CritColor := RED;
- SlackColor := BLUE;
- endif;
- invalidate(self);
- if gw invalidate(gw); endif;
- }!!
-
- /* Create a new Milestone */
- Def newMilestone(self)
- {
- newActivity(self, Milestone);
- }!!
-
- /* Create the window using a "main" window style. */
- Def create(self, par, wName, rect, style)
- {
- ^create(self:Window, nil, wName, rect,
- WS_OVERLAPPEDWINDOW bitOr WS_VSCROLL bitOr WS_HSCROLL);
- }!!
-
- /* Set up a dummy project, menus and the method table. */
- Def init(self)
- {
- setProject(self, new(Project));
- setAutoCalc(project, true);
- setView(self, #normal);
- setScrollBars(self);
- setMenus(self);
- checkMenuItem(self, PW_AUTOCALC);
- checkMenuItem(self, PW_COLOR);
- setMethTable(self);
- }!!
-
- /* Set the project. */
- Def setProject(self, aProject)
- {
- project := aProject;
- }!!
-
- /* Set the resolution for the size of nodes, spacing etc.
- based on the font text size. There are two views,
- normal and small. Both are based on text font size so
- that they will display adequately with any resolution. */
- Def setView(self, aView | hDC, ts)
- {
- view := aView;
- hDC := getContext(self); /* so we can get text size */
- ts := textSize(self, hDC); /* x is width, y is height */
- releaseContext(self, hDC);
- if view == #small
- boxWidth := x(ts) * 4;
- boxHSpace := x(ts)/2 + 1;
- boxHeight := y(ts) + 4;
- else
- boxWidth := asInt(x(ts)*8);
- boxHSpace := x(ts) + 2;
- boxHeight := y(ts) * 2;
- endif;
- activWidth := boxWidth + boxHSpace;
- reSize(self, 0, 0L); /* so scrolling is adjusted */
- }!!
-
- /* Set the scroll bar ranges and initial positions. */
- Def setScrollBars(self)
- {
- Call SetScrollRange(hWnd, SB_HORZ, 0, PW_MAX_COLS, 0);
- Call SetScrollRange(hWnd, SB_VERT, 0, PW_MAX_ROWS, 0);
- hScrollPos := vScrollPos := 0;
- }!!
-
- /* Set up the method table used for display options.
- Each of these methods should be applicable to all
- activities in the project, that is, both Milestones
- and Tasks. */
- Def setMethTable(self)
- {
- methTable := #(#getTime,
- #getSlack,
- #getCost,
- #getEarlyStart,
- #getEarlyFinish,
- #getLateStart,
- #getLateFinish);
- topMethod := 3;
- }!!
-
- /* Set the method to display info below each box.
- The offset refers to the position in the
- methTable. */
- Def setBotMethod(self, offset)
- {
- botMethod := offset;
- }!!
-
- /* Set the method to display info atop each box.
- The offset refers to the position in the
- methTable. */
- Def setTopMethod(self, offset)
- {
- topMethod := offset;
- }!!
-
- /* Add an about box and load menu resources.
- Set up the menu actions table. Each entry
- consists of a constant ID and a message
- that will be performed. */
- Def setMenus(self)
- {
- addAbout(self);
- loadMenu(self, "PWMenus");
- setMenu(self, hMenu);
-
- actions := new(Dictionary, 30);
-
- add(actions, PW_FILE_NEW, #fileNew);
- add(actions, PW_FILE_OPEN, #fileOpenAs);
- add(actions, PW_FILE_SAVE, #fileSave);
- add(actions, PW_FILE_SAVEAS, #fileSaveAs);
- add(actions, PW_FILE_PRINT, #print);
- add(actions, PW_FILE_PRINT_GRAPH, #printGraphs);
- add(actions, PW_FILE_SETTINGS, #printerSetup);
- add(actions, PW_RUN, #run);
- add(actions, PW_FILE_QUIT, #close);
- add(actions, PW_CLIP, #clipChart);
- add(actions, PW_ABOUT_ACTOR, #aboutActor);
- add(actions, PW_DEL_ACTIVITY, #deleteActivity);
- add(actions, PW_DEL_RESOURCE, #deleteResource);
- add(actions, PW_NEW_MSTONE, #newMilestone);
- add(actions, PW_NEW_TASK, #newTask);
- add(actions, PW_NEW_PERT, #newPERTTask);
- add(actions, PW_DISPLAY, #displaySettings);
- add(actions, PW_COLOR, #toggleColor);
- add(actions, PW_AUTOCALC, #autoCalc);
- add(actions, PW_CALC, #recalc);
- add(actions, PW_SHOWROOM, #showRoom);
- add(actions, PW_ZOOM, #zoom);
- add(actions, PW_VIEW_SUMMARY, #viewSummary);
- add(actions, PW_VIEW_ACTIVITIES, #showActivities);
- add(actions, PW_VIEW_GANTT, #gantt);
- add(actions, PW_VIEW_RESOURCES, #showResources);
- add(actions, PW_VIEW_RESOURCE, #editResource);
-
- /* keyboard accelerator commands */
-
- add(actions, PW_HELP, #help);
- add(actions, EDIT_HOME, #home);
- add(actions, PW_COMMAND_MODE, #commandMode);
- }!!
-
- /* Convert window coordinates to relative display coordinates. */
- Def windowToDisplay(self, wPoint)
- {
- ^point((x(wPoint) - boxHSpace) / activWidth + hScrollPos,
- (y(wPoint) - boxHeight) / (boxHeight*2) + vScrollPos);
- }!!
-
- /* Convert relative display entries to window coordinates.
- Uses dot notation for speed. */
- Def displayToWindow(self, dPoint)
- {
- ^point(boxHSpace + (dPoint.x - hScrollPos) * activWidth,
- boxHeight + (dPoint.y - vScrollPos) * boxHeight*2);
- }!!
-
- /* The name of application, used for captions. */
- Def appName(self)
- {
- ^loadString(PW_APPNAME);
- }!!
-
- /* Check if there is a file error and display an error box.
- Return the error number, 0 for no error. */
- Def checkError(self, aFile | errNo)
- {
- errNo := getError(aFile);
- if errNo <> 0
- beep();
- errorBox(loadString(PW_FILEERR1),
- loadString(PW_FILEERR2) + asString(aFile) +
- loadString(PW_FILEERR3) + asString(errNo) +
- loadString(50+errNo));
- endif;
- ^errNo;
- }!!
-
- /* Returns true if the node is visible in the window.
- Used to speed up redrawing. Uses dot notation for speed. */
- Def visible(self, aNode)
- {
- ^between(aNode.x, hScrollPos, maxVisCol + hScrollPos)
- cand between(aNode.y, vScrollPos, maxVisRow + vScrollPos);
- }!!
-
- /* Set up the cursor for use even if there is no mouse. */
- Def gotFocus(self, prevHwnd)
- {
- Call ShowCursor(1);
- }!!
-
- /* Return to normal use of cursor. */
- Def losingFocus(self, hWndNew)
- {
- Call ShowCursor(0);
- } !!
-
- /* Check if the project has been saved. */
- Def shouldClose(self)
- {
- ^checkClean(self)
- }!!
-
- /* Make sure the window knows that the project has changed. */
- Def dirty(self)
- {
- invalidate(self);
- dirty := true;
- if gw
- invalidate(gw);
- endif;
- }!!
-
- /* Returns boolean value true if the project has
- not changed since last save. If it is dirty,
- the user is prompted for confirmation. */
- Def checkClean(self)
- {
- ^ not(dirty) cor
- yesNoBox(loadString(PW_WARNING),
- loadString(PW_DISCARD)) == IDYES;
- }!!
-
- /* Get the offset of the botMethod. */
- Def getBotMethod(self)
- {
- ^botMethod;
- }!!
-
- /* Get the offset of the topMethod. */
- Def getTopMethod(self)
- {
- ^topMethod;
- }!!
-
- /* Resize the window. Adjust visible rows and cols. */
- Def reSize(self, wp, lp)
- {
- maxVisRow := bottom(clientRect(self)) / (boxHeight*2);
- maxVisCol := right(clientRect(self)) / activWidth;
- }!!
-
- /* Respond to MS-Windows messages to paint the window.
- Show the project as a network chart.
- Draw each visible node in its proper position.
- Display the name and any other info required.
- Then draw the lines to connect the outputs.
-
- The displayToWindow message converts a node's
- logical display position to windows coordinates.
-
- This could be further speeded up by repainting
- only the invalid rectangle.
- */
- Def paint(self, hDC |wPoint, x, y)
- {
- do(nodes(project),
- {using(aNode)
-
- wPoint := displayToWindow(self, pos(aNode));
- x := x(wPoint); /* horiz windows posn */
- y := y(wPoint); /* vert windows posn */
-
- if visible(self, aNode)
- draw(aNode, self, x, y, hDC); /* node knows how to draw */
- drawTextInfo(self, aNode, x, y, hDC);
- endIf;
- /* always draw connections since they may be visible */
- drawConnections(self, aNode, x, y, getOutputs(aNode), hDC);
- });
- }!!
-
- /* Draw lines connecting the nodes in the window.
- Uses early binding, dot notation and direct
- Windows calls for speed. */
- Def drawConnections(self, aNode, x, y, connectedNodes, hDC | wPoint)
- {
- do(connectedNodes,
- {using(output)
- Call MoveTo(hDC, x + boxWidth, y + boxHeight/2);
- wPoint := displayToWindow(self:ProjWindow, pos(output));
- Call LineTo(hDC, wPoint.x, wPoint.y + boxHeight/2);
-
- if critical(aNode:Activity) cand critical(output:Activity)
- Call MoveTo(hDC, x + boxWidth, y + boxHeight/2+1);
- Call LineTo(hDC, wPoint.x, wPoint.y + boxHeight/2+1);
- endif;
- });
- }!!
-
- /* Draw text info in the window. If the small view is
- being used, show less information.
- Uses early binding and dot notation for speed. */
- Def drawTextInfo(self, aNode, x, y, hDC | ts, str, strSize, offsetY, offsetX)
- {
- ts := textSize(self, hDC);
- offsetY := (boxHeight - ts.y) / 2;
- strSize := boxWidth / ts.x;
- if view == #small
- offsetX := 2; /* to make milestones look ok */
- else
- offsetX := 0;
- endif;
-
- str := subString(aNode.name, 0, strSize-1);
- Call SetTextColor(hDC, SlackColor);
- Call TextOut(hDC, x + offsetX + 2, y + offsetY, str, size(str));
-
- if critical(aNode)
- Call SetTextColor(hDC, CritColor);
- endif;
-
- if topMethod /* display above box */
- str := subString(asString(perform(aNode, methTable[topMethod])),0,strSize);
- Call TextOut(hDC, x + 2, y - ts.y, str, size(str));
- endif;
-
- if view ~= #small
- cand botMethod /* display below box */
- str := subString(asString(perform(aNode, methTable[botMethod])),0,strSize);
- Call TextOut(hDC, x + 2, y + boxHeight, str, size(str));
- endif;
- }!!
-
- /* Draw a task in the window.
- Uses early binding and direct Windows call for speed. */
- Def drawTask(self, aNode, x, y, hDC)
- {
- Call Rectangle(hDC, x, y, x + boxWidth, y + boxHeight);
- if critical(aNode:Activity)
- Call Rectangle(hDC, x+1, y+1, x + boxWidth-1, y + boxHeight-1);
- endif;
- }!!
-
- /* Draw a milestone in the window.
- Uses early binding and direct Windows call for speed. */
- Def drawMilestone(self, aNode, x, y, hDC)
- {
- Call RoundRect(hDC, x, y, x + boxWidth, y + boxHeight, 20,20);
- if critical(aNode:Activity)
- Call RoundRect(hDC, x+1, y+1, x + boxWidth-1, y + boxHeight-1, 17,17);
- endif;
- }!!
-
- /* Handle menu events, accelerator keys.
- Lookup the ID in the actions table, if found
- perform it. */
- Def command(self, wp, lp)
- {
- if actions[wp]
- perform(self, actions[wp]);
- else /* these keys might be accelerators */
- if wp == VK_UP cor wp == VK_DOWN cor
- wp == VK_RIGHT cor wp == VK_LEFT
- WM_KEYDOWN(self, wp, lp);
- else
- beep(); /* internal error! */
- errorBox(loadString(PW_ERROR1),
- loadString(PW_ERROR2) + asString(wp));
- endif;
- endif;
- }!!
-
- /* Go into "command mode" in response to a slash key accelerator.
- This simulates Lotus 1-2-3 style commands by sending an
- ALT key sysCommand message. */
- Def commandMode(self)
- {
- WM_SYSCOMMAND(self, 0xF100, 0L);
- }!!
-
- /* Get a filename from the user in responds to menu event.
- If the file has changed, check with the user.
- Send a fileOpen message to do the work. */
- /* Respond to menu choice to create a new project. */
- Def fileNew(self)
- {
- if checkClean(self)
- if gw
- close(gw);
- endif;
- fileName := nil;
- dirty := nil;
- setProject(self, new(Project));
- checkMenuItem(self, PW_AUTOCALC);
- setAutoCalc(project, true);
- setText(self, appName(self));
- editInfo(project);
- invalidate(self);
- endif;
- }!!
-
- /* Prompt the user for the filename to open.
- Use the new combo box type of file dialog. */
- Def fileOpenAs(self | dlg, file, reader)
- {
- if checkClean(self)
- dlg := new(FileDialog, "*."+loadString(PW_EXTENSION));
- if runModal(dlg, FILE_BOX, self) == IDOK
- fileName := loadFile(dlg);
- fileOpen(self, fileName);
- endif;
- endif;
- }!!
-
- /* Open the file named fName and read a project from disk.
- If a DOS error occurs (like file not found) then stop.
- Uses the Language Extensions I object storage facility.
- This method copies the file into a stream so that it
- can read faster. Also, the old project, file and stream
- are set to nil as soon as possible to free up memory. */
- Def fileOpen(self, fName | dlg, file, strm, reader)
- {
- showWaitCurs(); /* this takes a while */
- if gw
- close(gw); /* close old GanttWindow */
- endif;
- file := new(File); /* open the file etc. */
- setName(file, fName);
- open(file, 0);
- if checkError(self, file) == 0 /* no DOS errors */
- project := nil; /* free up memory */
-
- strm := streamOver(copyFrom(file, 0, length(file)));
- close(file);
- setText(self, appName(self)+": " + fName);
- reader := new(StoredObjectReader);
- project := readFrom(reader, strm); /* read the project */
- strm := nil; /* free up memory */
- setAutoCalc(project, true); /* other settings */
- checkMenuItem(self, PW_AUTOCALC);
- dirty := nil;
- invalidate(self); /* redraw the window */
- else
- fileName := nil; /* due to DOS error */
- endif;
- showOldCurs(); /* all done */
- }!!
-
- /* Respond to menu choice to save the file. If the file
- isn't yet named, prompt the user for a name. */
- Def fileSave(self)
- {
- if fileName
- fileSaveIt(self, fileName);
- else
- fileSaveAs(self);
- endif;
- }!!
-
- /* Save the project to disk with a new name. */
- Def fileSaveAs(self | dlg)
- {
- if not(fileName)
- fileName := getName(project)+"."+loadString(PW_EXTENSION);
- endif;
- dlg := new(InputDialog, loadString(PW_APPNAME),
- loadString(PW_SAVEPROJ), fileName);
- if runModal(dlg, INPUT_BOX, self) == IDOK
- fileName := getText(dlg);
- fileSaveIt(self, fileName);
- endif;
- }!!
-
- /* Save the project to disk with the filename fName.
- If a DOS error occurs (like file not found) stop.
- Uses the Language Extensions I object storage facility.
- Note: this will not save any global variables! */
- Def fileSaveIt(self, fName | file)
- {
- showWaitCurs(); /* this takes a while */
- file := new(File);
- setName(file, fName);
- create(file);
- if checkError(self, file) == 0 /* no DOS error */
- setText(self, appName(self) + ": " + fileName);
- storeOn(project, file, nil); /* write to file */
- close(file);
- dirty := false;
- else
- fileName := nil; /* due to DOS error */
- endif;
- showOldCurs();
- }!!
-
- /* Print a text summary of the project.
- Uses the Printer class. */
- Def print(self | prn)
- {
- prn := new(Printer);
- showWaitCurs(); /* takes a while */
- if start(prn, "Project", self) /* start printing */
- do(getInfoLines(project),
- {using(line)
- printLine(prn, line);
- });
- printLine(prn, " ");
- printLine(prn, " ");
- printLine(prn, loadString(PW_ACTIVT1)+":");
- printLine(prn, loadString(PW_ACTIVT2));
- printLine(prn, loadString(PW_ACTIVT3));
- printLine(prn, "--------------------------------------------");
- do(sortedActivities(project),
- {using(aNode)
- printLine(prn, getInfoLine(aNode));
- });
- if size(resources(project)) > 0
- printLine(prn, " ");
- printLine(prn, " ");
- printLine(prn, loadString(PW_REST1) + ":");
- printLine(prn, loadString(PW_REST2));
- printLine(prn, loadString(PW_REST3));
- printLine(prn, "------------------------------------------");
- do(resources(project),
- {using(aRes)
- printLine(prn, getInfoLine(aRes));
- });
- endif;
- finish(prn); /* all done */
- showOldCurs();
- else
- showOldCurs();
- beep();
- errorBox(loadString(PW_PRINTERR1),loadString(PW_PRINTERR2));
- endif;
- }!!
-
- /* Print graphics charts */
- Def printGraphs(self)
- {
- printWindow(self, 1);
- }!!
-
- /* Copy bitmap to clipboard */
- Def clipChart(self)
- {
- clipWindow(self, 1);
- }
-
- /* Create a new Milestone */
- Def newMilestone(self)
- {
- newActivity(self, Milestone);
- }!!
-
- /* Create a new Task */
- Def newTask(self)
- {
- newActivity(self, Task);
- }!!
-
- /* Create a new PERTTask */
- Def newPERTTask(self)
- {
- newActivity(self, PERTTask);
- }!!
-
- /* Create a new activity based on a menu choice.
- The nodeClass should be passed in as Task, Milestone etc.
- Return the new activity or nil if canceled. */
- Def newActivity(self, nodeClass | activity)
- {
- activity := new(nodeClass);
- setNetwork(activity, project);
- if editInfo(activity) == IDOK /* let user connect it */
- if pos(activity) = 0@0 /* still not connected */
- activity.y := 1; /* safe location */
- resetPosn(getNetwork(activity), activity, 0@0);
- endif;
- dirty(self); /* redraw etc. */
- ^activity;
- endif;
- ^nil;
- }!!
-
- /* Delete a resource in response to menu choice.
- Returns the deleted resource or nil if canceled. */
- Def deleteResource(self | dlg, name, res)
- {
- dlg := new(InputDialog, loadString(PW_DELRES1),
- loadString(PW_DELRES2), "");
- if runModal(dlg, INPUT_BOX, self) == IDOK
- name := getText(dlg);
- if res := checkResExists(project, name)
- delete(res, project);
- dirty(self);
- ^res;
- endif;
- endif;
- ^nil;
- }!!
-
- /* Delete an activity in response to menu choice.
- Returns the deleted node or nil if canceled. */
- Def deleteActivity(self | dlg, name, node)
- {
- dlg := new(InputDialog, loadString(PW_DELACT1),
- loadString(PW_DELACT2), "");
- if runModal(dlg, INPUT_BOX, self) == IDOK
- name := getText(dlg);
- if node := checkNodeExists(project, name)
- delete(node);
- dirty(self);
- ^node;
- endif;
- endif;
- ^nil
- }!!
-
- /* Edit a particular resource in response to menu choice.
- For now, ask the user which one. Return the resource
- or nil if canceled. */
- Def editResource(self | dlg, res)
- {
- dlg := new(InputDialog, loadString(PW_VIEWRES1), loadString(PW_VIEWRES2),"");
- if runModal(dlg, INPUT_BOX, self) == IDOK
- if res := checkResExists(project, getText(dlg))
- editInfo(res);
- dirty(self);
- ^res;
- endif;
- endif;
- ^nil;
- }!!
-
- /* Show all of the resources as in a TextWindow. */
- Def showResources(self | tw)
- {
- tw := new(TextWindow, self, nil, loadString(PW_REST1), nil);
- show(tw, 1);
- printLine(tw, loadString(PW_SHOWRES2));
- printLine(tw, "-----------------------------------------------");
- do(resources(project),
- {using(res)
- printLine(tw, getInfoLine(res));
- });
- }!!
-
- /* Show all of the activities in a TextWindow. */
- Def showActivities(self | tw)
- {
- tw := new(TextWindow, self, nil, loadString(PW_ACTIVT1), nil);
- show(tw, 1);
- printLine(tw, loadString(PW_SHOWACT2));
- printLine(tw, "------------------------------------------");
- do(sortedActivities(project),
- {using(aNode)
- printLine(tw, getInfoLine(aNode));
- });
- }!!
-
- /* Respond to menu choice to edit the project */
- Def viewSummary(self)
- {
- editInfo(project);
- }!!
-
- /* If the user presses the home key, reset scroll posn. */
- Def home(self)
- {
- hScrollPos := vScrollPos := 0;
- Call SetScrollPos(hWnd, SB_HORZ, hScrollPos, 1);
- Call SetScrollPos(hWnd, SB_VERT, vScrollPos, 1);
- invalidate(self);
- }!!
-
- /* If the right button is pressed, toggle the view
- to allow zoom in and out */
- Def zoom(self)
- {
- if view == #normal
- setView(self, #small);
- else
- setView(self, #normal);
- endif;
- invalidate(self);
- }!!
-
- /* Show the amount of memory available. */
- Def showRoom(self | temp)
- {
- temp := Call GlobalCompact(Call GlobalCompact(0)+16) / 1024;
-
- errorBox(loadString(PW_SHOWROOM1),
- asString(temp) + loadString(PW_SHOWROOM2));
- }!!
-
- /* Respond to menu choice to recalculate. */
- Def recalc(self)
- {
- showWaitCurs();
- recalc(project);
- invalidate(self);
- if gw
- invalidate(gw);
- endif;
- showOldCurs();
- }!!
-
- /* The ganttWindow has closed. */
- Def closeGantt(self)
- {
- gw := nil;
- enableMenuItem(self, PW_VIEW_GANTT);
- }!!
-
- /* Respond to menu choice to set display options. The user
- can select information to be displayed above or below
- the nodes in the window. */
- Def displaySettings(self | dlg)
- {
- dlg := new(PWSetDialog);
- if runModal(dlg, SETTING_BOX, self) == IDOK
- invalidate(self);
- endif;
- }!!
-
- /* Handle menu choice to create a Gantt chart.
- Create the window large enough to hold all of
- the activities, plus some extra space. */
- Def gantt(self | height)
- {
- if screenSize()=640@200
- height := 10
- else
- height := 20;
- endif;
- gw := new(GanttWindow, self, nil, loadString(PW_GANTT),
- rect(asInt(x(screenSize())/3),
- max(y(screenSize())-(size(project)+5)*height,10),
- x(screenSize()), y(screenSize())));
- setProject(gw, project);
- show(gw,1);
- grayMenuItem(self, PW_VIEW_GANTT);
- }!!
-
- /* Display help information from resource file. */
- Def help(self | dlg)
- {
- dlg := new(Dialog);
- checkRunModal(dlg, PW_HELP_BOX, self);
- }!!
-
- /* Display Actor information from resource file. */
- Def aboutActor(self | dlg)
- {
- dlg := new(Dialog);
- checkRunModal(dlg, PW_ABOUT_ACTOR_BOX, self);
- }!!
-
- /* Handles menu choice to set autocalc. */
- Def autoCalc(self)
- {
- if autoCalc(project)
- unCheckMenuItem(self, PW_AUTOCALC);
- setAutoCalc(project, false);
- else
- checkMenuItem(self, PW_AUTOCALC);
- setAutoCalc(project, true);
- recalc(self);
- endif;
- }!!
-
- /* See if the user has double clicked on a box.
- If so, bring up a dialog for editing. Return the
- activity or nil if canceled. */
- Def WM_LBUTTONDBLCLK(self, wp, lp | dPoint, activity)
- {
- dPoint := windowToDisplay(self, asPoint(lp));
- activity := displayLookup(project, dPoint);
- if activity /* logically true if found */
- if editInfo(activity) == IDOK /* user clicked on activity */
- dirty(self); /* changes were made */
- ^activity;
- endif;
- else /* false if nothing found */
- beep(); /* user clicked on dead space */
- endif;
- ^nil;
- }!!
-
- /* If the right button is pressed, toggle the view
- to allow zoom in and out */
- Def WM_RBUTTONDOWN(self, wp, lp)
- {
- zoom(self);
- }!!
-
- /* Trap keyboard events to simulate mouse. Cursor keys move
- the cursor and scroll, return and F2 edit an activity.
- Note anything defined as an accelerator will NOT cause
- a WM_KEYDOWN message. The keys W, X, A, D can also be
- used to move the cursor. */
- Def WM_KEYDOWN(self, wp, lp | pos, x, y, activity, max, dict)
- {
- pos := getCursorPos(self); /* client coords */
- x := x(pos);
- y := y(pos);
-
- select
- case wp == VK_UP or wp == asInt('W')
- y := y - boxHeight*2;
- endCase
- case wp == VK_DOWN or wp == asInt('X')
- y := y + boxHeight*2;
- endCase
- case wp == VK_LEFT or wp == asInt('A')
- x := x - activWidth;
- endCase
- case wp == VK_RIGHT or wp == asInt('D')
- x := x + activWidth;
- endCase
- case wp == VK_RETURN or wp == VK_F2
- WM_LBUTTONDBLCLK(self, 1, asLong(pos));
- endCase
- endSelect;
-
- /* If the cursor is moving off screen, scroll. */
-
- select
- case y < 0
- y := boxHeight;
- WM_VSCROLL(self, SB_LINEUP, 1);
- endCase
- case y > max:=maxVisRow*boxHeight*2
- y := max - boxHeight;
- WM_VSCROLL(self, SB_LINEDOWN, 1);
- endCase
- endSelect;
-
- select
- case x < 0
- x := boxHSpace;
- WM_HSCROLL(self, SB_LINEUP, 1);
- endCase
- case x > max:=maxVisCol*activWidth
- x := max - boxWidth;
- WM_HSCROLL(self, SB_LINEDOWN, 1);
- endCase
- endSelect;
-
- setCursorPos(self, point(x,y));
- }!!
-
- /* Trap scrolling. Adjust as necesary.
- The wp is the scroll code, the lp gives posn. */
- Def WM_HSCROLL(self, wp, lp | scroll)
- {
- select
- case wp == SB_LINEUP
- scroll := -1;
- endCase
- case wp == SB_LINEDOWN
- scroll := 1;
- endCase
- case wp == SB_PAGEUP
- scroll := negate(maxVisCol);
- endCase;
- case wp == SB_PAGEDOWN
- scroll := maxVisCol;
- endCase;
- case wp == SB_THUMBPOSITION
- hScrollPos := 0; scroll := low(lp);
- endCase;
- default
- scroll := nil;
- endSelect;
-
- if scroll
- hScrollPos := hScrollPos + scroll; /* adjust */
- hScrollPos := min(PW_MAX_COLS, max(0, hScrollPos));
- Call SetScrollPos(hWnd, SB_HORZ, hScrollPos, 1);
- invalidate(self);
- endif;
- }!!
-
- /* Trap scrolling. Adjust as necesary.
- The wp is the scroll code, the lp gives posn. */
- Def WM_VSCROLL(self, wp, lp | scroll)
- {
- select
- case wp == SB_LINEUP
- scroll := -1;
- endCase
- case wp == SB_LINEDOWN
- scroll := 1;
- endCase
- case wp == SB_PAGEUP
- scroll := negate(maxVisRow);
- endCase;
- case wp == SB_PAGEDOWN
- scroll := maxVisRow;
- endCase;
- case wp == SB_THUMBPOSITION
- vScrollPos := 0; scroll := low(lp);
- endCase;
- endSelect;
-
- if scroll
- vScrollPos := vScrollPos + scroll; /* adjust */
- vScrollPos := min(PW_MAX_ROWS, max(0, vScrollPos));
- Call SetScrollPos(hWnd, SB_VERT, vScrollPos, 1);
- invalidate(self);
- endif;
- }!!
-
-
- /* Begin dragging to allow the user to draw a line
- that will connect two boxes. Setup the anchorPt and
- dragDC to allow dragging to do the drawing.
- BW 02/05/89 */
- Def beginDrag(self, wp, aPt | dPoint, activity, dMode)
- {
- dPoint := windowToDisplay(self, aPt);
- activity := displayLookup(project, dPoint);
- if activity /* logically true if found */
- anchorPt := aPt;
- dragDC := getContext(self);
- dMode := Call SetROP2(dragDC,7);
- Call SelectObject(dragDC,Call GetStockObject(6));
- endif;
- }!!
-
- /* Do the drag and draw the feedback.
- BW 02/05/89 */
- Def drag(self, wp, aPt )
- { if dragDC then
- if oldPt cand (oldPt <> aPt)
- then moveTo(anchorPt,dragDC);
- lineTo(oldPt,dragDC);
- endif;
- oldPt := aPt;
- moveTo(anchorPt,dragDC);
- lineTo(aPt,dragDC);
- endif;
- }!!
-
- /* Finish the drag connection of two tasks.
- Create a new task if necessary. */
- Def endDrag(self, wp, aPt | dPoint1, dPoint2, activity1, activity2)
- {
- if dragDC then
- dPoint2 := windowToDisplay(self, aPt);
- activity2 := displayLookup(project, dPoint2);
- if activity2 /* logically true if found */
- dPoint1 := windowToDisplay(self,anchorPt);
- activity1 := displayLookup(project, dPoint1);
- if activity1 <> activity2
- connect(project,getName(activity1),
- getName(activity2));
- invalidate(self);
- endif;
- else /* maybe the user wants a new node */
- if activity2 := newActivity(self,Task) then
- dPoint1 := windowToDisplay(self,anchorPt);
- activity1 := displayLookup(project, dPoint1);
- connect(project,getName(activity1),
- getName(activity2));
- invalidate(self);
- else
- moveTo(anchorPt,dragDC); /* erase last line*/
- lineTo(oldPt,dragDC);
- endif;
- endif;
- releaseContext(self,dragDC); /* done drawing */
- dragDC := nil;
- oldPt := nil;
- endif;
- }!!
-
-